package java_class_work.week06.reflect;

import java.lang.reflect.*;

/**
 * @Auther: admin
 * @Date: 2022/10/18 14:41
 * @Description: 反射的应用
 */

public class ReflectDemo01 {
    public static void main(String[] args) {
        Class stuClass = Student.class;
        // 获取所有构造方法，但无法获取私有
        Constructor[] constructors = stuClass.getConstructors();
        for (Constructor con : constructors) {
            System.out.println(con);
            // 获取构造方法的参数 -> java.lang.String arg0,int arg1,int arg2,
            Parameter[] parameters = con.getParameters();
            for (Parameter para : parameters) {
                System.out.print(para + ",");
            }
        }
        // 获取所有的构造方法，包括私有
        Constructor[] dcon = stuClass.getDeclaredConstructors();
        for (Constructor c : dcon) {
            System.out.println(c);
        }
        /*
            public java_class_work.week06.reflect.Student(java.lang.String,int,int)
            private java_class_work.week06.reflect.Student(java.lang.String)
            public java_class_work.week06.reflect.Student()
       */

        //todo 获取指定的构造方法

        try {
            // 不能获取私有
            Constructor con1 = stuClass.getConstructor(String.class,int.class,int.class);
            System.out.println(con1);
            // 可获取私有构造方法
            Constructor con2 = stuClass.getDeclaredConstructor(String.class);
            System.out.println(con2);
            // 通过构造器 实例化对象,不能使用私有
            Student aniya = (Student)con1.newInstance("阿尼亚",6,0);
            System.out.println(aniya);
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        // 通过字节码对象 实例化（只能使用默认的无参构造方法）
        try {
            Student hu =(Student)stuClass.newInstance();
            hu.setName("胡适");
            System.out.println(hu);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        // 获取字段
        try {
            //获取指定公共字段
            Field height = stuClass.getField("height");
            System.out.println(height);
            //获取所有字段
            Field[] dfs = stuClass.getDeclaredFields();
            for (Field df : dfs) {
                System.out.println(df);
            }
            //获取指定私有字段
            Field name = stuClass.getDeclaredField("name");
            // 字段名
            System.out.println(name.getName());
            // 字段类型
            System.out.println(name.getType());
            // 实例化对象
            Student rose =(Student)stuClass.newInstance();
            // 打开设值权限（私有字段），否则无法访问私有字段
            name.setAccessible(true);
            name.set(rose,"rose");
            System.out.println(name.get(rose));

        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }

        // 获取所有公共方法，包括继承的
        System.out.println("获取所有公共方法==============");
        Method[] methods = stuClass.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }

        //获取所有方法，包括私有，但不包括继承
        System.out.println("===============");
        Method[] dm = stuClass.getDeclaredMethods();
        for (Method method : dm) {
            System.out.println(method.getName());
        }
        // 获取指定方法
        try {
            Method method01 = stuClass.getDeclaredMethod("method01", int.class, String.class);
            //参数个数
            System.out.println(method01.getParameterCount());
            // 实例化对象
            Student aniya =(Student)stuClass.newInstance();
            // 打开访问私有方法权限
            method01.setAccessible(true);
            // 调用方法 invoke
            method01.invoke(aniya, 1, "阿尼亚");

            // 调用有返回值的方法
            Method method02 = stuClass.getDeclaredMethod("method02");
            method02.setAccessible(true);
            int result = (int)method02.invoke(aniya);
            System.out.println(result);
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
